package com.ssy.lingxi.marketing.serviceimpl;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.constant.marketing.MerchantCouponTypeEnum;
import com.ssy.lingxi.common.constant.marketing.PlatformCouponTypeEnum;
import com.ssy.lingxi.common.model.dto.UserLoginCacheDTO;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.marketing.entity.coupon.*;
import com.ssy.lingxi.marketing.model.constant.MerchantCouponGetWayEnum;
import com.ssy.lingxi.marketing.model.constant.MerchantCouponStatusEnum;
import com.ssy.lingxi.marketing.model.constant.PlatformCouponGetWayEnum;
import com.ssy.lingxi.marketing.model.constant.PlatformCouponStatusEnum;
import com.ssy.lingxi.marketing.model.vo.coupon.request.ActivityPageCouponDetailRequest;
import com.ssy.lingxi.marketing.model.vo.coupon.request.ActivityPageMerchantCouponRequest;
import com.ssy.lingxi.marketing.model.vo.coupon.request.BelongTypeCouponRequest;
import com.ssy.lingxi.marketing.model.vo.coupon.response.ActivityPageCouponDetailResponse;
import com.ssy.lingxi.marketing.model.vo.coupon.response.ActivityPageCouponPageResponse;
import com.ssy.lingxi.marketing.repository.MerchantCouponRepository;
import com.ssy.lingxi.marketing.repository.PlatformCouponRepository;
import com.ssy.lingxi.marketing.service.IActivityPageCouponService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 平台、商家活动页优惠券服务实现类
 * @author yzc
 * @version 2.0.0
 * @date 2021/8/13
 */
@Slf4j
@Service
public class ActivityPageCouponServiceImpl implements IActivityPageCouponService {

    @Resource
    private MerchantCouponRepository merchantCouponRepository;

    @Resource
    private PlatformCouponRepository platformCouponRepository;

    @Resource
    private JPAQueryFactory queryFactory;

    /**
     * 平台营销活动页 - 选择平台优惠券
     * @return 返回结果
     */
    @Override
    public Wrapper<PageData<ActivityPageCouponPageResponse>> pagePlatformActivityPagePlatformCoupon(ActivityPageMerchantCouponRequest request, UserLoginCacheDTO loginUser) {
        // 待执行,执行中
        List<Integer> statusList = Arrays.asList(PlatformCouponStatusEnum.WAIT_EXECUTE.getCode(), PlatformCouponStatusEnum.EXECUTING.getCode());

        QPlatformCouponDO couponDO = QPlatformCouponDO.platformCouponDO;
        QCouponShopDO shopDO = QCouponShopDO.couponShopDO;

        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(couponDO.memberId.eq(loginUser.getMemberId()));
        predicates.and(couponDO.roleId.eq(loginUser.getMemberRoleId()));
        predicates.and(shopDO.shopId.eq(request.getShopId()));
        // 状态
        predicates.and(couponDO.status.in(statusList));

        // 当前时间在发券时间内
        long currentTimeMillis = System.currentTimeMillis();
        predicates.and(couponDO.releaseTimeStart.loe(currentTimeMillis));
        predicates.and(couponDO.releaseTimeEnd.goe(currentTimeMillis));

        // 非0元购买抵扣券
        predicates.and(couponDO.type.eq(PlatformCouponTypeEnum.COMMON.getCode()));

        // 前台用户领券
        predicates.and(couponDO.getWay.eq(PlatformCouponGetWayEnum.FRONT.getCode()));

        if (Objects.nonNull(request.getId())) {
            predicates.and(couponDO.id.eq(request.getId()));
        }

        if (StringUtils.isNotEmpty(request.getName())) {
            predicates.and(couponDO.name.like("%" + request.getName() + "%"));
        }

        JPAQuery<PlatformCouponDO> queryJpaQuery = queryFactory.select(couponDO)
                .from(couponDO)
                .leftJoin(shopDO).on(couponDO.id.eq(shopDO.couponId).and(shopDO.belongType.eq(BelongTypeEnum.PLATFORM.getCode())));

        queryJpaQuery.where(predicates);

        //总条数
        long totalCount = queryJpaQuery.fetchCount();
        List<PlatformCouponDO> pageList = queryJpaQuery.orderBy(couponDO.releaseTimeStart.desc())
                .offset(request.getCurrentOffset())
                .limit(request.getPageSize())
                .fetch();

        List<ActivityPageCouponPageResponse> resultList = pageList.stream().map(coupon -> {
            ActivityPageCouponPageResponse response = new ActivityPageCouponPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(PlatformCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(PlatformCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setUseConditionMoney(coupon.getUseConditionMoney());
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setCreateTime(coupon.getCreateTime());
            response.setBelongType(BelongTypeEnum.PLATFORM.getCode());
            response.setBelongName(BelongTypeEnum.PLATFORM.getMessage());
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(totalCount, resultList));
    }

    /**
     * 商家营销活动页 - 选择商家优惠券
     * @return 返回结果
     */
    @Override
    public Wrapper<PageData<ActivityPageCouponPageResponse>> pageMerchantActivityPageMerchantCoupon(ActivityPageMerchantCouponRequest request, UserLoginCacheDTO loginUser) {
        // 待执行,执行中
        List<Integer> statusList = Arrays.asList(MerchantCouponStatusEnum.WAIT_EXECUTE.getCode(), MerchantCouponStatusEnum.EXECUTING.getCode());
        // 非0元购买抵扣券
        List<Integer> typeList = Arrays.asList(MerchantCouponTypeEnum.COMMON.getCode(),
                MerchantCouponTypeEnum.CATEGORY.getCode(),
                MerchantCouponTypeEnum.BRAND.getCode(),
                MerchantCouponTypeEnum.COMMODITY.getCode());

        QMerchantCouponDO couponDO = QMerchantCouponDO.merchantCouponDO;
        QCouponShopDO shopDO = QCouponShopDO.couponShopDO;

        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(couponDO.memberId.eq(loginUser.getMemberId()));
        predicates.and(couponDO.roleId.eq(loginUser.getMemberRoleId()));
        predicates.and(shopDO.shopId.eq(request.getShopId()));
        // 状态
        predicates.and(couponDO.status.in(statusList));

        // 当前时间在发券时间内
        long currentTimeMillis = System.currentTimeMillis();
        predicates.and(couponDO.releaseTimeStart.loe(currentTimeMillis));
        predicates.and(couponDO.releaseTimeEnd.goe(currentTimeMillis));

        // 非0元购买抵扣券
        predicates.and(couponDO.type.in(typeList));

        // 前台用户领券
        predicates.and(couponDO.getWay.eq(MerchantCouponGetWayEnum.FRONT.getCode()));

        if (Objects.nonNull(request.getId())) {
            predicates.and(couponDO.id.eq(request.getId()));
        }

        if (StringUtils.isNotEmpty(request.getName())) {
            predicates.and(couponDO.name.like("%" + request.getName() + "%"));
        }

        JPAQuery<MerchantCouponDO> queryJpaQuery = queryFactory.select(couponDO)
                .from(couponDO)
                .leftJoin(shopDO).on(couponDO.id.eq(shopDO.couponId).and(shopDO.belongType.eq(BelongTypeEnum.MERCHANT.getCode())));

        queryJpaQuery.where(predicates);

        //总条数
        long totalCount = queryJpaQuery.fetchCount();
        List<MerchantCouponDO> pageList = queryJpaQuery.orderBy(couponDO.releaseTimeStart.desc())
                .offset(request.getCurrentOffset())
                .limit(request.getPageSize())
                .fetch();

        List<ActivityPageCouponPageResponse> resultList = pageList.stream().map(coupon -> {
            ActivityPageCouponPageResponse response = new ActivityPageCouponPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setUseConditionMoney(coupon.getUseConditionMoney());
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setCreateTime(coupon.getCreateTime());
            response.setBelongType(BelongTypeEnum.MERCHANT.getCode());
            response.setBelongName(coupon.getMemberName());
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(totalCount, resultList));
    }

    /**
     * 平台营销活动页 - 选择商家优惠券
     * @return 返回结果
     */
    @Override
    public Wrapper<PageData<ActivityPageCouponPageResponse>> pagePlatformActivityPageMerchantCoupon(ActivityPageMerchantCouponRequest request, UserLoginCacheDTO loginUser) {
        // 待执行,执行中
        List<Integer> statusList = Arrays.asList(MerchantCouponStatusEnum.WAIT_EXECUTE.getCode(), MerchantCouponStatusEnum.EXECUTING.getCode());
        // 非0元购买抵扣券
        List<Integer> typeList = Arrays.asList(MerchantCouponTypeEnum.COMMON.getCode(),
                MerchantCouponTypeEnum.CATEGORY.getCode(),
                MerchantCouponTypeEnum.BRAND.getCode(),
                MerchantCouponTypeEnum.COMMODITY.getCode());

        QMerchantCouponDO couponDO = QMerchantCouponDO.merchantCouponDO;
        QCouponShopDO shopDO = QCouponShopDO.couponShopDO;

        BooleanBuilder predicates = new BooleanBuilder();
        predicates.and(shopDO.shopId.eq(request.getShopId()));

        // 状态
        predicates.and(couponDO.status.in(statusList));

        // 当前时间在发券时间内
        long currentTimeMillis = System.currentTimeMillis();
        predicates.and(couponDO.releaseTimeStart.loe(currentTimeMillis));
        predicates.and(couponDO.releaseTimeEnd.goe(currentTimeMillis));

        // 非0元购买抵扣券
        predicates.and(couponDO.type.in(typeList));

        // 前台用户领券
        predicates.and(couponDO.getWay.eq(MerchantCouponGetWayEnum.FRONT.getCode()));

        if (Objects.nonNull(request.getId())) {
            predicates.and(couponDO.id.eq(request.getId()));
        }

        if (StringUtils.isNotEmpty(request.getName())) {
            predicates.and(couponDO.name.like("%" + request.getName() + "%"));
        }

        JPAQuery<MerchantCouponDO> queryJpaQuery = queryFactory.select(couponDO)
                .from(couponDO)
                .leftJoin(shopDO).on(couponDO.id.eq(shopDO.couponId).and(shopDO.belongType.eq(BelongTypeEnum.MERCHANT.getCode())));

        queryJpaQuery.where(predicates);

        //总条数
        long totalCount = queryJpaQuery.fetchCount();
        List<MerchantCouponDO> pageList = queryJpaQuery.orderBy(couponDO.releaseTimeStart.desc())
                .offset(request.getCurrentOffset())
                .limit(request.getPageSize())
                .fetch();

        List<ActivityPageCouponPageResponse> resultList = pageList.stream().map(coupon -> {
            ActivityPageCouponPageResponse response = new ActivityPageCouponPageResponse();
            response.setId(coupon.getId());
            response.setName(coupon.getName());
            response.setType(coupon.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(coupon.getType()));
            response.setReleaseTimeStart(coupon.getReleaseTimeStart());
            response.setReleaseTimeEnd(coupon.getReleaseTimeEnd());
            response.setDenomination(coupon.getDenomination());
            response.setGetWay(coupon.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(coupon.getGetWay()));
            response.setUseConditionMoney(coupon.getUseConditionMoney());
            response.setEffectiveType(coupon.getEffectiveType());
            response.setEffectiveTimeStart(coupon.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(coupon.getEffectiveTimeEnd());
            response.setInvalidDay(coupon.getInvalidDay());
            response.setCreateTime(coupon.getCreateTime());
            response.setBelongType(BelongTypeEnum.MERCHANT.getCode());
            response.setBelongName(coupon.getMemberName());
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(new PageData<>(totalCount, resultList));
    }

    /**
     * 平台活动页 - 优惠券详情
     * @return 返回结果
     */
    @Override
    public Wrapper<List<ActivityPageCouponDetailResponse>> listPlatformActivityPageCouponDetail(ActivityPageCouponDetailRequest request, UserLoginCacheDTO loginUser) {
        // 返回
        List<ActivityPageCouponDetailResponse> resultList = new ArrayList<>();
        if (CollectionUtils.isEmpty(request.getCouponList())) {
            return Wrapper.success(resultList);
        }

        // belongType - couponIdList
        Map<Integer, List<Long>> belongTypeCouponMap = request.getCouponList().stream().collect(Collectors.groupingBy(BelongTypeCouponRequest::getBelongType, Collectors.mapping(BelongTypeCouponRequest::getCouponId, Collectors.toList())));
        for (Map.Entry<Integer, List<Long>> entry : belongTypeCouponMap.entrySet()) {
            Integer couponType = entry.getKey();
            List<Long> couponIdList = entry.getValue();
            if (BelongTypeEnum.PLATFORM.getCode().equals(couponType)) {
                List<PlatformCouponDO> platformCouponDOList = platformCouponRepository.findAllById(couponIdList);

                List<ActivityPageCouponDetailResponse> pageCouponDetailResponseList = platformCouponDOList.stream().map(e -> {
                    ActivityPageCouponDetailResponse response = new ActivityPageCouponDetailResponse();
                    response.setId(e.getId());
                    response.setName(e.getName());
                    response.setType(e.getType());
                    response.setTypeName(PlatformCouponTypeEnum.getCodeMessage(e.getType()));
                    response.setReleaseTimeStart(e.getReleaseTimeStart());
                    response.setReleaseTimeEnd(e.getReleaseTimeEnd());
                    response.setDenomination(e.getDenomination());
                    response.setGetWay(e.getGetWay());
                    response.setGetWayName(PlatformCouponGetWayEnum.getCodeMessage(e.getGetWay()));
                    response.setUseConditionMoney(e.getUseConditionMoney());
                    response.setEffectiveType(e.getEffectiveType());
                    response.setEffectiveTimeStart(e.getEffectiveTimeStart());
                    response.setEffectiveTimeEnd(e.getEffectiveTimeEnd());
                    response.setInvalidDay(e.getInvalidDay());
                    response.setCreateTime(e.getCreateTime());
                    response.setBelongType(BelongTypeEnum.PLATFORM.getCode());
                    response.setBelongName(BelongTypeEnum.PLATFORM.getMessage());
                    return response;
                }).collect(Collectors.toList());
                resultList.addAll(pageCouponDetailResponseList);
            } else if (BelongTypeEnum.MERCHANT.getCode().equals(couponType)) {
                List<MerchantCouponDO> merchantCouponDOList = merchantCouponRepository.findAllById(couponIdList);

                List<ActivityPageCouponDetailResponse> pageCouponDetailResponseList = merchantCouponDOList.stream().map(e -> {
                    ActivityPageCouponDetailResponse response = new ActivityPageCouponDetailResponse();
                    response.setId(e.getId());
                    response.setName(e.getName());
                    response.setType(e.getType());
                    response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(e.getType()));
                    response.setReleaseTimeStart(e.getReleaseTimeStart());
                    response.setReleaseTimeEnd(e.getReleaseTimeEnd());
                    response.setDenomination(e.getDenomination());
                    response.setGetWay(e.getGetWay());
                    response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(e.getGetWay()));
                    response.setUseConditionMoney(e.getUseConditionMoney());
                    response.setEffectiveType(e.getEffectiveType());
                    response.setEffectiveTimeStart(e.getEffectiveTimeStart());
                    response.setEffectiveTimeEnd(e.getEffectiveTimeEnd());
                    response.setInvalidDay(e.getInvalidDay());
                    response.setCreateTime(e.getCreateTime());
                    response.setBelongType(BelongTypeEnum.MERCHANT.getCode());
                    response.setBelongName(e.getMemberName());
                    return response;
                }).collect(Collectors.toList());
                resultList.addAll(pageCouponDetailResponseList);
            }
        }

        return Wrapper.success(resultList);
    }

    /**
     * 商家活动页 - 优惠券详情
     * @return 返回结果
     */
    @Override
    public Wrapper<List<ActivityPageCouponDetailResponse>> listMerchantActivityPageCouponDetail(ActivityPageCouponDetailRequest request, UserLoginCacheDTO loginUser) {
        List<Long> couponIds = request.getCouponList().stream().filter(e -> BelongTypeEnum.MERCHANT.getCode().equals(e.getBelongType())).map(BelongTypeCouponRequest::getCouponId).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(couponIds)) {
            return Wrapper.success(Collections.emptyList());
        }

        List<MerchantCouponDO> merchantCouponDOList = merchantCouponRepository.findAllById(couponIds);

        List<ActivityPageCouponDetailResponse> pageCouponDetailResponseList = merchantCouponDOList.stream().map(e -> {
            ActivityPageCouponDetailResponse response = new ActivityPageCouponDetailResponse();
            response.setId(e.getId());
            response.setName(e.getName());
            response.setType(e.getType());
            response.setTypeName(MerchantCouponTypeEnum.getCodeMessage(e.getType()));
            response.setReleaseTimeStart(e.getReleaseTimeStart());
            response.setReleaseTimeEnd(e.getReleaseTimeEnd());
            response.setDenomination(e.getDenomination());
            response.setGetWay(e.getGetWay());
            response.setGetWayName(MerchantCouponGetWayEnum.getCodeMessage(e.getGetWay()));
            response.setUseConditionMoney(e.getUseConditionMoney());
            response.setEffectiveType(e.getEffectiveType());
            response.setEffectiveTimeStart(e.getEffectiveTimeStart());
            response.setEffectiveTimeEnd(e.getEffectiveTimeEnd());
            response.setInvalidDay(e.getInvalidDay());
            response.setCreateTime(e.getCreateTime());
            response.setBelongType(BelongTypeEnum.MERCHANT.getCode());
            response.setBelongName(e.getMemberName());
            return response;
        }).collect(Collectors.toList());

        return Wrapper.success(pageCouponDetailResponseList);
    }

}
